package com.zxy.util;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Date;

@Slf4j
@Aspect
@Component
public class TypeAspect {
    /**
     * 拦截所有添加了AnnactionAOP注解的方法
     */
    @Before("@annotation(annactionAOP)")
    public void beforeMethod(JoinPoint joinPoint, AnnactionAOP annactionAOP) throws IllegalAccessException {
        log.info("进入AOP============================");
        // 获取注解的值
        Type annotationValue = annactionAOP.value();

        // 获取目标对象(方法的参数)
        Object[] args = joinPoint.getArgs();
        if (args == null || args.length == 0) {
            return;
        }

        // 这里假设第一个参数是需要设置日期字段的实体对象
        Object targetObject = args[0];

        // 获取当前时间
        Date currentTime = new Date();

        // 根据注解值设置不同的字段
        if (Type.CREATE.equals(annotationValue)) {
            // 若是CREATE类型，同时设置createTime和updateTime
            setFieldValue(targetObject, "createTime", currentTime);
            setFieldValue(targetObject, "updateTime", currentTime);
        } else if (Type.UPDATE.equals(annotationValue)) {
            // 若是UPDATE类型，只设置updateTime
            setFieldValue(targetObject, "updateTime", currentTime);
        }
    }

    /**
     * 利用反射给对象的指定字段设置值
     */
    private void setFieldValue(Object obj, String fieldName, Date value) throws IllegalAccessException {
        if (obj == null) {
            return;
        }

        Class<?> clazz = obj.getClass();
        // 遍历类及其父类，查找字段
        while (clazz != null) {
            try {
                Field field = clazz.getDeclaredField(fieldName);
                // 设置私有字段可访问
                field.setAccessible(true);
                // 设置字段值
                field.set(obj, value);
                return;
            } catch (NoSuchFieldException e) {
                // 如果当前类没有该字段，则查找父类
                clazz = clazz.getSuperclass();
            }
        }
    }

}
